/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	ComponentModelFilter.cpp
*
*	Comments	-	See ComponentModelFilter.h
*
**************************************************************************************/
#include "../Include/ComponentModelFilter.h"
#include "../Include/GraphicsResourceManager.h"
#include "../Include/Model.h"
#include "../Include/Actor.h"
#include "../Include/EventModelLoaded.h"
#include "../Include/EventModelUnload.h"
#include "../Include/GlobalGraphicsStrings.h"

namespace Pulse
{
	ComponentModelFilter::ComponentModelFilter( Actor *pOwner )
		: IComponent( pOwner )
	{
		m_pModel = PSX_NULL;
	}

	ComponentModelFilter::~ComponentModelFilter( void )
	{
		ReleaseModel();
	}

	EErrorCode::Type ComponentModelFilter::Initialize( XMLElementPtr pElem )
	{
		return EErrorCode::OKAY;
	}

	EErrorCode::Type ComponentModelFilter::LoadModel( const CHAR *pFilename )
	{
		ReleaseModel();

		GraphicsResourceManager *pGM = GraphicsResourceManager::GetInstance();
		ModelDesc desc;

		desc.SetToLoad( pFilename );
		m_pModel = pGM->CreateModel( &desc );

		if ( m_pModel == PSX_NULL )
		{
			PSX_PushWarning( "Failed to load model." );
			return EErrorCode::_ERROR;
		}

		// Create model renderer if not avaialble.
		IComponent *pComp = m_pOwner->AddComponent( EComponent::RENDERER );

		if ( pComp == PSX_NULL )
		{
			PSX_PushError( "Failed to create model renderer component." );
		}
		pComp = PSX_NULL;

		//TODO: Check effect requirements for any procedural requirements such as reflection
		{
			Material *pMat = m_pModel->GetMaterial();
			Effect *pEffect = pMat->GetEffect();
			SIZE_T numMaterialRequirements = pEffect->GetNumMaterialRequirements();
			MaterialElementRequirement *pMatRequirements = pEffect->GetMaterialRequirements();

			for ( SIZE_T i = 0; i < numMaterialRequirements; ++i )
			{
				MaterialElementRequirement *pMatElem = &pMatRequirements[i];

				if ( pMatElem->m_source == EMaterialSource::SYSTEM )
				{
					// Planar Reflection
					if ( pMatElem->m_type == EParameter::TEXTURE2D && pMatElem->m_name == GFX_PARAM_TEXTURE_PLANAR_REFLECTION )
					{
						// The reflection component will handle the rest...
						pComp = m_pOwner->AddComponent( EComponent::REFLECTION );

						if ( pComp == PSX_NULL )
						{
							PSX_PushError( "Failed to create component." );
						}
						pComp = PSX_NULL;
					}
				}
				else
				{
					continue;
				}
			}

			PSX_SafeRelease( pEffect );
			PSX_SafeRelease( pMat );
		}

		// Send event
		{
			EventModelLoaded event;

			event.SetModel( m_pModel );

			m_pOwner->ExecuteEvent( &event );
		}

		return EErrorCode::OKAY;
	}

	Model * ComponentModelFilter::GetModel( void )
	{
		if ( m_pModel )
		{
			m_pModel->AddRef();
			return m_pModel; 
		}

		return PSX_NULL;
	}


	void ComponentModelFilter::ReleaseModel( void )
	{
		m_pOwner->ExecuteEvent( &EventModelUnload() );

		PSX_SafeRelease( m_pModel );
	}

}